package com.caizongzhen.www.controller;

import cn.hutool.core.util.StrUtil;
import com.caizongzhen.www.dto.VerifyParaDto;
import com.caizongzhen.www.entity.User;
import com.caizongzhen.www.service.UserService;
import com.caizongzhen.www.util.Assert;
import com.caizongzhen.www.util.EmailClient;
import com.caizongzhen.www.util.RespResult;
import com.caizongzhen.www.util.VerifyFormat;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpRequest;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.util.Date;
import java.util.Map;

@Controller
//在控制器上添加@RequestMapping("/login")：表示控制器内方法，都必须要以/login作为上一级路径，如：/login/sendEmailCode
@RequestMapping("/login")
public class LoginController {
    @Autowired
    protected EmailClient emailClient;
    @Autowired
    protected HttpSession session;
    @Autowired
    protected HttpServletRequest request;
    @Autowired
    protected HttpServletResponse response;
    @Autowired
    protected UserService userService;


    /**
     * 发送邮箱验证码
     */
    @PostMapping("/sendEmailCode")
    // 将响应数据通过适当的转换器转换为指定的格式后，再写入响应体中返回数据，通常是：JSON格式数据 或 XML格式数据
    // 表示服务端返回JSON数据
    @ResponseBody
    // Map<String, Object> map：会自动创建一个Map对象到方法中
    public RespResult sendEmailCode(String email, Map<String, Object> map) {
        // StrUtil：字符串工具类
        if (StrUtil.isEmpty(email)) {
            return RespResult.fail("邮箱不可为空");
        }
        if(!VerifyFormat.verifyFormatEmail(email)){
            return RespResult.fail("请输入合法的邮箱地址");
        }
        // 发送验证码
        String verifyCode = emailClient.sendEmailCode(email);
        map.put("email", email);
        map.put("code", verifyCode);
        map.put("time", new Date());
        // 将邮箱信息 写入 session会话 当中
        session.setAttribute("EMAIL_CODE" + email, map);
        // 响应结果
        return RespResult.success("发送成功");
    }


    /**
     * 在每个子类方法调用之前先调用
     */
    @ModelAttribute
    public void setReqAndRes(HttpServletRequest request, HttpServletResponse response) {
        System.out.println("1111");
        //初始化请求对象 响应对象 会话对象
        this.request = request;
        this.response = response;
        this.session = request.getSession(true);
        //loginUser = (User) session.getAttribute("loginUser");
        //session.setAttribute("kindList", illnessKindService.findList());
    }


    /*
    * 用户注册
    * */
    @PostMapping("/register")
    // 将响应数据通过适当的转换器转换为指定的格式后，再写入响应体中返回数据，通常是：JSON格式数据 或 XML格式数据
    // 表示服务端返回JSON数据
    @ResponseBody
    // Map<String, Object> map：会自动创建一个Map对象到方法中
    public RespResult register(User user, String code) {
        // 判断传入的参数是否为空
        VerifyParaDto judgeResult = registerVerifyPara(user);
        if (!judgeResult.Tag) {
            return RespResult.fail(judgeResult.Msg);
        }
        // 判断邮箱、手机号格式是否正确
        VerifyParaDto verifyFormatResult = registerVerifyFormat(user);
        if(!verifyFormatResult.Tag) {
            return RespResult.fail(verifyFormatResult.Msg);
        }
        // 验证邮箱验证码code，是否正确且有效
        VerifyParaDto verifyEmailCode = registerVerifyEmailCode(user.getUserEmail(),code);
        if (!verifyEmailCode.Tag) {
            return RespResult.fail(verifyEmailCode.Msg);
        }

        // 判断 当前账户在数据库中是否已经存在
        User user1 = userService.findUserByUserAccount(user);
        if (!Assert.isEmpty(user1)) {
            return RespResult.fail("该账号已被注册");
        }
        // 创建时间、更新时间
        user.setCreateTime(new Date());
        user.setUpdateTime(new Date());
        if (userService.save(user)) {
            return RespResult.success("注册成功");
        }
        return RespResult.fail("注册失败");
    }


    /*
    * 用户登录
    * */
    @PostMapping("/login")
    // 将响应数据通过适当的转换器转换为指定的格式后，再写入响应体中返回数据，通常是：JSON格式数据 或 XML格式数据
    // 表示服务端返回JSON数据
    @ResponseBody
    public RespResult login(User user) {
        // 判断 当前账户在数据库中是否已经存在
        User user1 = userService.findUserByUserAccount(user);
        if (Assert.isEmpty(user1)) {
            // 判断密码是否正确
            return RespResult.fail("输入的账户不存在");
        }
        // 判断密码是否正确
        if(!user1.getUserPwd().equals(user.getUserPwd())) {
            return RespResult.fail("密码不正确");
        }
        // 更新数据登录时间
        user1.setUpdateTime(new Date());
        if (userService.saveOrUpdate(user1)) {
            // 将用户的账户写入session中
            session.setAttribute("loginUser",user1);
            return RespResult.success("登录成功");
        }
        return  RespResult.fail("登录失败");
    }


    /*
    * 验证邮箱验证码
    * */
    private  VerifyParaDto registerVerifyEmailCode(String email,String code){
        VerifyParaDto verifyParaDto = new VerifyParaDto();
        // 获取 会话 中的 code
        Map<String,Object> sessionMapCode = (Map<String,Object>)session.getAttribute("EMAIL_CODE" + email);
        if (Assert.isEmpty(sessionMapCode)){
            verifyParaDto.Tag = false;
            verifyParaDto.Msg = "请先获取验证码";
            return verifyParaDto;
        }
        // 获取验证码时间
        Date time = (Date) sessionMapCode.get("time");
        // 判断 输入的 code 是否与 sessionCode 是否相同
        String sessionCode = (String) sessionMapCode.get("code");

        if(!sessionCode.equals(code)) {
            verifyParaDto.Tag = false;
            verifyParaDto.Msg = "输入的邮箱验证码有误";
            return verifyParaDto;
        }
        // 判断验证码的有效时间失效
        if (System.currentTimeMillis() - time.getTime() > 5*60*1000) {
            verifyParaDto.Tag = false;
            verifyParaDto.Msg = "邮箱验证码超出有效时间，请重新获取验证码";
            // 清除 session 中的邮箱验证码
//            session.removeAttribute("EMAIL_CODE" + email);
        }
        verifyParaDto.Tag = true;
        return verifyParaDto;
    }


    /*
    * 验证手机号、邮箱格式
    * */
    private VerifyParaDto registerVerifyFormat(User user){
        VerifyParaDto verifyParaDto = new VerifyParaDto();
        verifyParaDto.Tag = false;
        if (!VerifyFormat.verifyFormatEmail(user.getUserEmail())) {
            verifyParaDto.Msg = "邮箱格式不正确";
            return verifyParaDto;
        }
        System.out.println(VerifyFormat.verifyFormatMobile(user.getUserTel()));
        if(!VerifyFormat.verifyFormatMobile(user.getUserTel())){
            verifyParaDto.Msg = "手机号格式不正确";
            return  verifyParaDto;
        }
        verifyParaDto.Tag = true;
        return verifyParaDto;
    }


    /*
    * 验证注册 参数 是否为空
    * */
    private VerifyParaDto registerVerifyPara(User user){
        VerifyParaDto verifyParaDto = new VerifyParaDto();
        verifyParaDto.Tag = false;
        // 判断参数是否为空
        if (Assert.isEmpty(user.getUserEmail())) {
            verifyParaDto.Msg = "邮箱不能为空";
            return verifyParaDto;
        }
        else if (Assert.isEmpty(user.getUserName())) {
            verifyParaDto.Msg = "姓名不能为空";
            return verifyParaDto;
        }
        else if (Assert.isEmpty(user.getUserAccount())) {
            verifyParaDto.Msg = "登录账户不能为空";
            return verifyParaDto;
        }
        else if (Assert.isEmpty(user.getUserPwd())) {
            verifyParaDto.Msg = "密码不能为空";
            return verifyParaDto;
        }
        else if (Assert.isEmpty(user.getUserTel())) {
            verifyParaDto.Msg = "手机号不能为空";
            return verifyParaDto;
        }
        else if (Assert.isEmpty(user.getUserAge())) {
            verifyParaDto.Msg = "年龄不能为空";
            return verifyParaDto;
        }
        else if (Assert.isEmpty(user.getUserSex())) {
            verifyParaDto.Msg = "性别不能为空";
            return verifyParaDto;
        }
        else {
            verifyParaDto.Tag = true;
            return verifyParaDto;
        }
    }
}
